package com.music.lib.xiami;

import com.lcx.exbean.LogBean;

import java.net.URLDecoder;
import java.util.*;

/**
 * 虾米下载地址解析
 */
public class XiamiUrlReader {

    private static final LogBean logger = LogBean.getLogger(XiamiUrlReader.class);

    public static void main(String[] args) throws Exception{

        //8%2.4E3%581Fy255e%Eba28n76%25%1a%7EE35d9F.e%35F_5.u36--8Eb8%xt24E31EmtD4%c9e8%2i%F79456ph1%55eeb5Fa21%62243_55E8288EmmF%29717%k3E-3f%ed1i35F67133e8%%56555
        readUrl("6%mie5114F8413t%65%Eb89%5%21at8582121_%h36E5-4145E5F2m%%866768l3_D3%E2f95E7E%8i22%16792.Fk145-c9c12222..FF22%133mae58E%1137fcFxn17F526_9puy3%-59eb5%9");

    }

    //方案一  优先使用方案一，如果方案一解析失败使用方案二
    static String readUrl(String str) throws Exception{
        //https://m128.xiami.net/347/106347/309696/3427755_1521180647311.mp3?auth_key=1536375600-0-0-65c1ff9429337c2c46b2b2b6da2b8f69
        //https://m128.xiami.net/347/106347/309696/3427755_1521180647311.mp3?auth_key=1536375600-0-0-65c1ff9429337c2c46b2b2b6da2b8f69

        //8%2.4E3%581Fy355fc2f28n76%25%1a%7EE92b6F.e%35F_5.u35--4c69%xt24E31EmtD6%624d2i%F79456ph1%5596aFa21%62243_55Ec3b2mmF%29717%k3E-132b1i35F67133e6%%f7b8

        //依据 m128.xiami.net规则进行拆分，其中它肯定不会超过这个长度。
        //第一个数字是要分割为几行，%忽略。


        //第一步，解析关键字
//        String str = "8%2.4E3%581Fy355fc2f28n76%25%1a%7EE92b6F.e%35F_5.u35--4c69%xt24E31EmtD6%624d2i%F79456ph1%5596aFa21%62243_55Ec3b2mmF%29717%k3E-132b1i35F67133e6%%f7b8";
//        String str = "6%mie614%14E%63t%65%E3f%b121at96122_955%h33E5-6d5dfF2m%%94F613E83_D7%E7b4Ebf%8i22%21954%.Fk155-658bf22..FF2877%75mae56E%fa4ee5Fxn17F57754Epuy3%-5d16985";
        // 8%2.47192ph15--772E28n7%%%43_5E%c6a29F.e%2251%k3%5c1a34%xt2FFE73e65E6d4e82i%F11__Fy4E-d%6f7Fa22252la%6%%254dmmF3653.u3255dE6%1i34543mtD%EE72b5
        //9%8e2153mh5%Ed5652.tF253p_35-2EbEFx%26423k6E%d229%i23594%e4%577242aF41%13y65E7a38Fm37%57F%2E-6ae7mi4%2E_a3%-c14f1.72F_luD5%cd6d2n%F12.t1E56%4%
        //8%2.4E3%517%k3%597b7e28n76%2%133e65E6a65F.e%35F581Fy4E-34cf%xt24E3E%1a%6%%%f5c2i%F794_5.u3255551fFa21%621EmtD%EEE5c3mmF%29756ph15--2fd61i35F67243_5E%a6e3a
        //6%mie%FE526%5627mae5%%E67d579a21at521E112E715puy355-d%7Eb31F2m%E198%3F22153t%6EE%85969%%8i2815%5114_96%h34%-51E7ad52..F%%22E1871493_D65%E21689EFxn225%F31%558.Fk12E5-e5%77e
        //5%F.i%7327F813_3ue14E%5dfb67b2mx.2%4F82477l%ty58%5E2edd52F1inF2714%%_3.3h%345E-38c4b1%2ae4F76%5537mF_36%E-56918bf28mt72%82EE98pakD55-%ec34af5
        //9%8e2FFE73y4-58db2.tF1218F%8%e942Fx%26%7_a345d381%i2385_luD%E2baf2aF47E3.t15-3d75Fm47889mh5E%6c5mi77443p_3%5c1b1.7%%%73k65Ef4b2n%2253%e5E-e6f
        //6%mie5114F8413t%65%Eb89%5%21at8582121_%h36E5-4145E5F2m%%866768l3_D3%E2f95E7E%8i22%16792.Fk145-c9c12222..FF22%133mae58E%1137fcFxn17F526_9puy3%-59eb5%9
        System.out.println("虾米加密地址："+str);
        int line = Integer.parseInt(str.substring(0,1));
        int vag = str.length()/line;
        str = str.substring(2);
        String key = "m128.xiami.net%2F";
        String keys[] = new String[line];
        for(int i=0,j=0;i<key.length();i++,j++){
            if(j>keys.length-1){
                j=0;
            }
            if(keys[j] == null){
                keys[j] = String.valueOf(key.charAt(i));
            }else{
                keys[j] += String.valueOf(key.charAt(i));
            }
        }
        //第二步，依据关键字查找index
        int indics[] = new int[line];
        List<Map<String,Integer>> keysList = new LinkedList<>();
        Map<String,Integer> map;
        for(int i=0;i<keys.length;i++) {
            map = new HashMap<>(1);
            map.put(keys[i],i);
            keysList.add(map);
        }
        int count = 0;
        for(int i=0,j=0;i<str.length() && count<indics.length;i+=vag,j++){
            int index = i==0?0:i-2;
            boolean hasFound = false;
            while(!hasFound){
                Map.Entry<String,Integer> k;
                for(int v=0;v<keysList.size();v++){
                    k = keysList.get(v).entrySet().iterator().next();
                    int end = index+k.getKey().length();
                    String s = str.substring(index,end>str.length()?str.length():end);
                    if(s.equals(k.getKey())){
                        indics[k.getValue()] = index;
                        hasFound = true;
                        count ++;
                        i = index;
                        keysList.remove(v);
                        break;
                    }
                    if(end == str.length()) break;
                }
                index++;
                if(index>i+2 || index>str.length()-1) break;
            }
        }

        //第三步，排序：
        int copy_indics[] = new int[indics.length];
        System.arraycopy(indics,0,copy_indics,0,indics.length);
        Arrays.sort(copy_indics);


        //第四步，拆分字符
        String []results = new String[copy_indics.length];
        for(int i=0;i<results.length;i++){
            if(i<results.length-1)
                results[i] = str.substring(copy_indics[i],copy_indics[i+1]);
            else
                results[i] = str.substring(copy_indics[i]);
        }


        //第五步  字符排序
        String newResult[] = new String[copy_indics.length];
        for(int i=0;i<copy_indics.length;i++){
            for(int j=0;j<indics.length;j++){
                if(copy_indics[i] == indics[j]){
                    newResult[j] = results[i];
                    break;
                }
            }
        }

        //第六步 组装为可解析的数据
        int max = 0;
        for(int i=0;i<results.length;i++){
            max = Math.max(max,results[i].length());
        }
        StringBuilder builder = new StringBuilder();
        int j=0;
        there:for(int i=0;;i++){
            String s = newResult[i];
            if(j>max-1) break there;
            for(;j<s.length();){
                String t = String.valueOf(s.charAt(j));
                builder.append(t);
                break;
            }
            if(i>=newResult.length-1) {
                i=-1;
                j++;
            }
        }

        //第七步  去除异常字符
        String urlEnc = builder.toString();
        while(urlEnc.endsWith("%") || urlEnc.endsWith("F") || urlEnc.endsWith("%2") || urlEnc.endsWith("%F")){
            if(urlEnc.endsWith("%") || urlEnc.endsWith("F")){
                urlEnc = urlEnc.substring(0,urlEnc.length()-1);
            }else{
                urlEnc = urlEnc.substring(0,urlEnc.length()-2);
            }
        }

        logger.debug("初步筛选："+urlEnc);


        //第八步  解析
        String urlDesc = URLDecoder.decode(urlEnc,"UTF-8");

        logger.debug("初步筛选解析后："+urlDesc);

        //第九步 剔除尾部混淆字符
        int Findex = urlDesc.lastIndexOf("-")+1;
        String token = urlDesc.substring(Findex);
        if(token.length()>32){
            urlDesc = urlDesc.substring(0,urlDesc.length()-(token.length()-32));
        }

        logger.debug("初步筛选剔除混淆字符："+urlDesc);


        //第十步 替换非法字符
        urlDesc = urlDesc.replaceAll("\\^","0");

        logger.debug("虾米解密后地址："+urlDesc);
        System.out.println("虾米解密后地址："+urlDesc);

        //8%

        //mmF%29717%k3E-132b
        //1i35F67133e6%%f7b8
        //2.4E3%581Fy355fc2f2
        //8n76%25%1a%7EE92b6F
        //.e%35F_5.u35--4c69%
        //xt24E31EmtD6%624d2
        //i%F79456ph1%5596aF
        //a21%62243_55Ec3b2

        return urlDesc;
    }


    private static void test1() throws Exception{
        //https://m128.xiami.net/169/7169/414285/1771269774_1509347400658.mp3?auth_key=1536375600-0-0-76fd36b5a1fd48460be9bdbfe81ff2552F/
        //https://m128.xiami.net/169/7169/414285/1771269774_1509347400658.mp3?auth_key=1536375600-0-0-76fd36b5a1fd48460be9bdbfe81ff255

        //6%mie614%14E%63t%65%E3f%b121at96122_955%h33E5-6d5dfF2m%%94F613E83_D7%E7b4Ebf%8i22%21954%.Fk155-658bf22..FF2877%75mae56E%fa4ee5Fxn17F57754Epuy3%-5d16985


        //6%
        // 2  F  % 2

        //mie614%14E%63t%65%E3f%b12
        //1at96122_955%h33E5-6d5dfF
        //2m%%94F613E83_D7%E7b4Ebf%
        //8i22%21954%.Fk155-658bf22
        //..FF2877%75mae56E%fa4ee5F
        //xn17F57754Epuy3%-5d16985


        String str[] = new String[]{
                "mie614%14E%63t%65%E3f%b12",
                "1at96122_955%h33E5-6d5dfF",
                "2m%%94F613E83_D7%E7b4Ebf%",
                "8i22%21954%.Fk155-658bf22",
                "..FF2877%75mae56E%fa4ee5F",
                "xn17F57754Epuy3%-5d16985"
        };

        StringBuilder builder = new StringBuilder();
        int j=0;
        there:for(int i=0;;i++){
            String s = str[i];
            if(j>s.length()-1) break there;
            for(;j<s.length();){
                String t = String.valueOf(s.charAt(j));
                builder.append(t);
                break;
            }
            if(i>=str.length-1) {
                i=-1;
                j++;
            }
        }
        System.out.println(builder.toString());
        System.out.println(URLDecoder.decode(builder.toString(),"UTF-8").replaceAll("\\^","0"));
    }



    private static void test3() throws Exception{
        String str[] = new String[]{
                "mmF%29717%k3E-132b",
                "1i35F67133e6%%f7b8",
                "2.4E3%581Fy355fc2f2",
                "8n76%25%1a%7EE92b6F",
                ".e%35F_5.u35--4c69%",
                "xt24E31EmtD6%624d2",
                "i%F79456ph1%5596aF",
                "a21%62243_55Ec3b2"
        };
        int max = 0;
        for(int i=0;i<str.length;i++){
            max = Math.max(max,str[i].length());
        }
        StringBuilder builder = new StringBuilder();
        int j=0;
        for(int i=0;;i++){
            String s = str[i];
            if(j>max-1) break;
            if(j<s.length()){
                String t = String.valueOf(s.charAt(j));
                builder.append(t);
            }
            if(i>=str.length-1) {
                i=-1;
                j++;
            }
        }
        System.out.println(URLDecoder.decode("https://m128.xiami.net%2F347%2F1%5E6347%2F3%5E9696%2F3427755_152118%5E647311.mp3%3Fauth_key%3D15363756%5E%5E-%5E-%5E-65c1ff9429337c2c46b2b2b6da2b8f69","UTF-8").replaceAll("\\^","0"));
        System.out.println(builder.toString());
        System.out.println(URLDecoder.decode(builder.toString(),"UTF-8").replaceAll("\\^","0"));
    }

}
